-module(matrix).

-export([divide/1, modify_inlet/2, modify_outlet/2]).

-compile(export_all).

-include("scatter_region.hrl").

-include_lib("eunit/include/eunit.hrl").
-define(MO, ?MODULE).

calc_entrylet(Entrylet, {Begin, End} = _EntryRange, {From,To} = _NeighbourRange) ->
    if 
        End > Begin ->
            Delta = 1;
        Begin > End ->
            Delta = -1;
        true ->
            Delta = 0
    end,
    Mid = (Begin + End) / 2.0,
    if
        From >= Mid ->
            (12 + Entrylet + Delta) rem 12;
        To =< Mid ->
            (12 + Entrylet - Delta) rem 12;
        true ->
            throw("WRong")
    end.

modify_inlet(#topological_region{inlet=OldIn} = TR, {_From, _To} = PredRange) ->
    NewIn = calc_entrylet(OldIn, edge_range(TR, OldIn), PredRange),
    TR#topological_region{inlet = NewIn}.

modify_outlet(#topological_region{outlet=OldOut} = TR, {_From, _To} = PredRange) ->
    NewOut = calc_entrylet(OldOut, edge_range(TR, OldOut), PredRange),
    TR#topological_region{outlet = NewOut}.

edge_range(#topological_region{region={left=Left, right=Right}}, 0) ->
    {Left, Right};
edge_range(#topological_region{region={top=Top, bottom=Bottom}}, 3) ->
    {Top, Bottom};
edge_range(#topological_region{region={left=Left, right=Right}}, 6) ->
    {Right, Left};
edge_range(#topological_region{region={top=Top, bottom=Bottom}}, 9) ->
    {Bottom, Top};
edge_range(#topological_region{region={top=Top}}, _Entry) ->
    {Top, Top}.


divide(#topological_region{inlet=undefined, outlet=undefined, region=Region}) ->
    if 
        abs(Region#region.top - Region#region.bottom) >= abs(Region#region.right - Region#region.left) ->
            {Left, Right} = divide_vertical(Region),
            TR1 = #topological_region{inlet=4, outlet=2, square_flag=false, region=Left},
            TR2 = #topological_region{inlet=10,outlet=8, square_flag=false, region=Right},
            {TR1, TR2};
        true ->
            {Top, Bottom} = divide_horizonal(Region),
            TR1 = #topological_region{inlet=7, outlet=5, square_flag=false, region=Top},
            TR2 = #topological_region{inlet=5, outlet=7, square_flag=false, region=Bottom},
            {TR1, TR2}
    end;
divide(#topological_region{square_flag=true} = TopologicalRegion) ->
    divide_square(TopologicalRegion);
divide(#topological_region{square_flag=false} = TopologicalRegion) ->
    divide_rectangle(TopologicalRegion).

crosscut(#topological_region{inlet=0, outlet=Out}=TopologicalRegion) ->
    R = TopologicalRegion#topological_region.region,
    {TopRegion, BottomRegion} = divide_horizonal(R),
    case Out of
        4 ->
            Top = #topological_region{inlet=0,outlet=6, region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=3, region=BottomRegion},
            {Top,Bottom};
        6 ->
            Top = #topological_region{inlet=0,outlet=6, region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=6, region=BottomRegion},
            {Top,Bottom};
        8 ->
            Top = #topological_region{inlet=0,outlet=6, region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=9, region=BottomRegion},
            {Top,Bottom}
    end;
crosscut(#topological_region{inlet=2, outlet=Out}=TopologicalRegion) ->
    R = TopologicalRegion#topological_region.region,
    {TopRegion, BottomRegion} = divide_horizonal(R),
    case Out of
        4 ->
            Top = #topological_region{inlet=3,outlet=6,region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=3,region=BottomRegion},
            {Top,Bottom};
        6 ->
            Top = #topological_region{inlet=3,outlet=6,region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=6,region=BottomRegion},
            {Top,Bottom};
        8 ->
            Top = #topological_region{inlet=3,outlet=6,region=TopRegion},
            Bottom = #topological_region{inlet=0,outlet=9,region=BottomRegion},
            {Top,Bottom}
    end;
crosscut(#topological_region{inlet=4, outlet=Out} = TopologicalRegion) ->
    R = TopologicalRegion#topological_region.region,
    {TopRegion, BottomRegion} = divide_horizonal(R),
    case Out of
        10 ->
            Top = #topological_region{inlet=6,outlet=9,region=TopRegion},
            Bottom = #topological_region{inlet=3,outlet=0,region=BottomRegion},
            {Top,Bottom};
        0 ->
            Top = #topological_region{inlet=6,outlet=0,region=TopRegion},
            Bottom = #topological_region{inlet=3,outlet=0,region=BottomRegion},
            {Top,Bottom};
        2 ->
            Top = #topological_region{inlet=6,outlet=3,region=TopRegion},
            Bottom = #topological_region{inlet=3,outlet=0,region=BottomRegion},
            {Top,Bottom}
    end.

divide_rectangle(#topological_region{inlet=In, region=#region{left=L,top=T,right=R,bottom=B}} = TopologicalRegion) 
when (abs(B-T) > abs(R-L)) ->
    if 
        (In == 0) or (In == 2) ->
            to_squares(crosscut(TopologicalRegion));
        (In == 4) ->
            {TR1, TR2} = crosscut(TopologicalRegion),
            to_squares({TR2, TR1});
        (In == 6) or (In == 8) ->
            {M1,M2} = crosscut(rotate_counterclockwise_quarter(rotate_counterclockwise_quarter(TopologicalRegion))),
            to_squares({rotate_clockwise_quarter(rotate_clockwise_quarter(M1)),
                    rotate_clockwise_quarter(rotate_clockwise_quarter(M2))});
        (In == 10) ->
            {M1,M2} = crosscut(rotate_counterclockwise_quarter(rotate_counterclockwise_quarter(TopologicalRegion))),
            to_squares({rotate_clockwise_quarter(rotate_clockwise_quarter(M2)),
                    rotate_clockwise_quarter(rotate_clockwise_quarter(M1))});
        true ->
            throw("sHouLd nOt be Here!")
    end;
divide_rectangle(#topological_region{inlet=In} = TopologicalRegion) ->
    if 
        (In == 1) ->
            {M1,M2} = crosscut(rotate_clockwise_quarter(TopologicalRegion)),
            to_squares({rotate_counterclockwise_quarter(M2), rotate_counterclockwise_quarter(M1)});
        (In == 11) or (In == 9) ->
            {M1,M2} = crosscut(rotate_clockwise_quarter(TopologicalRegion)),
            to_squares({rotate_counterclockwise_quarter(M1), rotate_counterclockwise_quarter(M2)});
        (In == 3) or (In == 5) ->
            {M1,M2} = crosscut(rotate_counterclockwise_quarter(TopologicalRegion)),
            to_squares({rotate_clockwise_quarter(M1), rotate_clockwise_quarter(M2)});
        (In == 7) ->
            {M1,M2} = crosscut(rotate_counterclockwise_quarter(TopologicalRegion)),
            to_squares({rotate_clockwise_quarter(M2), rotate_clockwise_quarter(M1)});
        true ->
            throw("SHold NoT be hERe!")
    end.

to_rectangle(TR) ->
    TR#topological_region{square_flag=false}.
to_square(TR) ->
    TR#topological_region{square_flag=true}.

to_rectangles({TR1, TR2}) ->
    {to_rectangle(TR1), to_rectangle(TR2)}.
to_squares({TR1, TR2}) ->
    {to_square(TR1), to_square(TR2)}.

cut(#topological_region{inlet=In, outlet=Out}=TopologicalRegion) when (In == 1) or (In == 2) ->
    R = TopologicalRegion#topological_region.region,
    case Out of
        3 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = shrink_vertical(In, TopRegion),
            TR2 = #topological_region{inlet=11, outlet=Out, region=BottomRegion},
            {TR1, TR2};
%        (Out > 3) and (Out < 6) ->
        4 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = shrink_vertical(In, TopRegion),
            TR2 = #topological_region{inlet=11, outlet=Out-1, region=BottomRegion},
            {TR1, TR2};
        5 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = shrink_vertical(In, TopRegion),
            TR2 = #topological_region{inlet=11, outlet=Out, region=BottomRegion},
            {TR1, TR2};
        6 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = shrink_vertical(In, TopRegion),
            TR2 = #topological_region{inlet=11, outlet=Out-1, region=BottomRegion},
            {TR1, TR2};

        9 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = shrink_horizonal(In, RightRegion),
            TR2 = #topological_region{inlet=4, outlet=Out+1, region=LeftRegion},
            {TR1, TR2};
%        (Out > 9) and (Out < 12) ->
        10 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR2 = #topological_region{inlet=4, outlet=Out, region=LeftRegion},
            TR1 = shrink_horizonal(In, RightRegion),
            {TR1, TR2};
        11 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR2 = #topological_region{inlet=4, outlet=0, region=LeftRegion},
            TR1 = shrink_horizonal(In, RightRegion),
            {TR1, TR2};
        0 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR2 = #topological_region{inlet=4, outlet=Out, region=LeftRegion},
            TR1 = shrink_horizonal(In, RightRegion),
            {TR1, TR2}
    end;
cut(#topological_region{inlet=0, outlet=Out}=TopologicalRegion) ->
    R = TopologicalRegion#topological_region.region,
    case Out of
        1 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = #topological_region{inlet=0, outlet=4, region=LeftRegion},
            TR2 = #topological_region{inlet=8, outlet=0, region=RightRegion},
            {TR1, TR2};
        2 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = #topological_region{inlet=0, outlet=4, region=LeftRegion},
            TR2 = #topological_region{inlet=8, outlet=Out, region=RightRegion},
            {TR1, TR2};
        3 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = #topological_region{inlet=0, outlet=4, region=LeftRegion},
            TR2 = #topological_region{inlet=8, outlet=2, region=RightRegion},
            {TR1, TR2};
        4 ->    
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=1, outlet=7, region=TopRegion},
            TR2 = #topological_region{inlet=11, outlet=3, region=BottomRegion},
            {TR1, TR2};
        5 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=1, outlet=7, region=TopRegion},
            TR2 = #topological_region{inlet=11, outlet=5, region=BottomRegion},
            {TR1, TR2};
        6 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=1, outlet=7, region=TopRegion},
            TR2 = #topological_region{inlet=11, outlet=5, region=BottomRegion},
            {TR1, TR2};
        7 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=11, outlet=5, region=TopRegion},
            TR2 = #topological_region{inlet=1, outlet=Out, region=BottomRegion},
            {TR1, TR2};
        8 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=11, outlet=5, region=TopRegion},
            TR2 = #topological_region{inlet=1, outlet=9, region=BottomRegion},
            {TR1, TR2};
        9 ->
            {TopRegion, BottomRegion} = divide_horizonal(R),
            TR1 = #topological_region{inlet=11, outlet=5, region=TopRegion},
            TR2 = #topological_region{inlet=1, outlet=9, region=BottomRegion},
            {TR1, TR2};
        10 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = #topological_region{inlet=0, outlet=8, region=RightRegion},
            TR2 = #topological_region{inlet=4, outlet=Out, region=LeftRegion},
            {TR1, TR2};
        11 ->
            {LeftRegion, RightRegion} = divide_vertical(R),
            TR1 = #topological_region{inlet=0, outlet=8, region=RightRegion},
            TR2 = #topological_region{inlet=4, outlet=0, region=LeftRegion},
            {TR1, TR2}
    end.
        
divide_square(#topological_region{inlet=In}=TopologicalRegion) when (In == 0) or (In == 1) or (In == 2) ->
    to_rectangles(cut(TopologicalRegion));
divide_square(#topological_region{inlet=In}=TopologicalRegion) when (In == 3) or (In == 4) or (In == 5) ->
    TR = rotate_counterclockwise_quarter(TopologicalRegion),
    {M1,M2} = cut(TR),
    to_rectangles({rotate_clockwise_quarter(M1), rotate_clockwise_quarter(M2)});
divide_square(#topological_region{inlet=In}=TopologicalRegion) when (In == 6) or (In == 7) or (In == 8) ->
    TR = rotate_counterclockwise_quarter(rotate_counterclockwise_quarter(TopologicalRegion)),
    {M1,M2} = cut(TR),
    to_rectangles({rotate_clockwise_quarter(rotate_clockwise_quarter(M1)),
            rotate_clockwise_quarter(rotate_clockwise_quarter(M2))});
divide_square(#topological_region{inlet=In}=TopologicalRegion) when (In == 9) or (In == 10) or (In == 11) ->
    TR = rotate_clockwise_quarter(TopologicalRegion),
    {M1,M2} = cut(TR),
    to_rectangles({rotate_counterclockwise_quarter(M1),
            rotate_counterclockwise_quarter(M2)}).

shrink_vertical(In, TopRegion) ->
    case In of
        1 ->
            #topological_region{inlet=In, outlet=7, region=TopRegion};
        2 ->
            #topological_region{inlet=3, outlet=7, region=TopRegion}
    end.

divide_horizonal(#region{top=T,left=L,bottom=B,right=R}) ->
    Top = #region{top=T, left=L, right=R, bottom=T+(B-T)/2},
    Bottom = #region{top=T+(B-T)/2, left=L, right=R, bottom=B},
    {Top, Bottom}.

divide_vertical(#region{top=T, left=L, bottom=B, right=R}) ->
    Left = #region{top=T, left=L, right=L+(R-L)/2, bottom=B},
    Right = #region{top=T, left=L+(R-L)/2, right=R, bottom=B},
    {Left, Right}.

shrink_horizonal(In, RightRegion) ->
    case In of
        1 ->
            #topological_region{inlet=0, outlet=8, region=RightRegion};
        2 ->
            #topological_region{inlet=In, outlet=8, region=RightRegion}
    end.

%%
%% rotate counterclockwise
rotate_ccw_quarter(#region{left=L,top=T,right=R,bottom=B}) ->
    #region{left=-T, top=R, right=-B, bottom=L}.

%%
%% rotate cloclkwise
rotate_cw_quarter(#region{left=L,top=T,right=R,bottom=B}) ->
    #region{left=B, top=-L, right=T,bottom=-R}.


%%
%%
%%
%%
rotate_clockwise_quarter(#topological_region{inlet=In, outlet=Out, region=Region}) ->
    #topological_region{
        inlet = (In + 3) rem 12, 
        outlet = (Out + 3) rem 12,
        region = rotate_cw_quarter(Region)
    }.

rotate_counterclockwise_quarter(#topological_region{inlet=In, outlet=Out, region=Region}) ->
    #topological_region{
        inlet = (In + 9) rem 12,
        outlet = (Out + 9) rem 12,
        region = rotate_ccw_quarter(Region)
    }.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% unit test
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%% 
%%  +---+
%%  |   |
%%  |   |
%%  |   |
%%  +---+
%%
divide_rectangle_0_4_test() ->
    TR = #topological_region{inlet=0, square_flag=false,
        outlet=4, region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=3, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).
    
divide_rectangle_0_6_test() ->
    TR = #topological_region{inlet=0, outlet=6,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_0_8_test() ->
    TR = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=9, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).


divide_rectangle_2_4_test() ->
    TR = #topological_region{inlet=2, outlet=4,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=3, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_2_6_test() ->
    TR = #topological_region{inlet=2, outlet=6,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_2_8_test() ->
    TR = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=9, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_4_2_test() ->
    TR = #topological_region{inlet=4, outlet=2,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=3, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=3, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_4_10_test() ->
    TR = #topological_region{inlet=4, outlet=10,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=9, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=3, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assert(Top#topological_region.square_flag),
    ?assert(Bottom#topological_region.square_flag),
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_4_0_test() ->
    TR = #topological_region{inlet=4, outlet=0,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=3, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_6_0_test() ->
    TR = #topological_region{inlet=6, outlet=0,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_6_2_test() ->
    TR = #topological_region{inlet=6, outlet=2,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=3, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_6_10_test() ->
    TR = #topological_region{inlet=6, outlet=10,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=9, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_8_10_test() ->
    TR = #topological_region{inlet=8, outlet=10,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=9, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=9, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_8_2_test() ->
    TR = #topological_region{inlet=8, outlet=2, square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=3, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=9, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_8_0_test() ->
    TR = #topological_region{inlet=8, outlet=0,square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=6, outlet=0, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=9, outlet=0, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_10_4_test() ->
    TR = #topological_region{inlet=10, outlet=4, square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top, Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=9, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=3, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_10_6_test() ->
    TR = #topological_region{inlet=10, outlet=6, square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top, Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=9, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=6, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_rectangle_10_8_test() ->
    TR = #topological_region{inlet=10, outlet=8, square_flag=false,
        region=#region{left=20.0,top=60.0, right=40.0, bottom=20.0}},
    {Top, Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=9, outlet=6, 
        region=#region{left=20.0,top=60.0,right=40.0,bottom=40.0}},
    ExpectBottom = #topological_region{inlet=0, outlet=9, 
        region=#region{left=20.0,top=40.0,right=40.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).
%%
%% +---------+
%% |         |
%% |         |
%% +---------+
%% 
divide_rectangle_1_7_test() ->
    TR = #topological_region{inlet=1, outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=3, outlet=6, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=9, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_9_1_test() ->
    TR = #topological_region{inlet=9, outlet=1,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=9, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=0, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_11_1_test() ->
    TR = #topological_region{inlet=11, outlet=1,square_flag=false,
        region=#region{left=20.0,top=30.0, right=60.0, bottom=10.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=3, 
        region=#region{left=20.0,top=30.0,right=40.0,bottom=10.0}},
    ExpectRight = #topological_region{inlet=9, outlet=0, 
        region=#region{left=40.0,top=30.0,right=60.0,bottom=10.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_11_3_test() ->
    TR = #topological_region{inlet=11, outlet=1,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=0, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assert(Left#topological_region.square_flag),
    ?assert(Right#topological_region.square_flag),
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_11_5_test() ->
    TR = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=6, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assert(Left#topological_region.square_flag),
    ?assert(Right#topological_region.square_flag),
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_7_1_test() ->
    TR = #topological_region{inlet=7, outlet=1,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left, Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=6, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=0, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assert(Left#topological_region.square_flag),
    ?assert(Right#topological_region.square_flag),
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_7_3_test() ->
    TR = #topological_region{inlet=7, outlet=3,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left, Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=6, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=3, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_7_5_test() ->
    TR = #topological_region{inlet=7, outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=6, outlet=3, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=9, outlet=6, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_5_7_test() ->
    TR = #topological_region{inlet=5, outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=3, outlet=6, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=6, outlet=9, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_rectangle_5_11_test() ->
    TR = #topological_region{inlet=5, outlet=11,square_flag=false,
        region=#region{left=10.0,top=100.0, right=120.0, bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=3, outlet=0, 
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=6, outlet=9, 
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (1, 2) -> [3,4,5,6,7,8,9,10,11] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
divide_square_1_3_test() ->
    TR = #topological_region{inlet=1, 
        outlet=3, region=#region{left=0.0,top=100.0, right=100.0, bottom=0.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1, outlet=7, square_flag=false,
        region=#region{left=0.0,top=100.0,right=100.0,bottom=50.0}},
    ExpectBottom = #topological_region{inlet=11,outlet=3, square_flag=false,
        region=#region{left=0.0,top=50.0,right=100.0,bottom=0.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_2_3_test() ->
    TR = #topological_region{inlet=2, 
        outlet=3, region=#region{left=0.0,top=100.0, right=100.0, bottom=0.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3, outlet=7, square_flag=false,
        region=#region{left=0.0,top=100.0,right=100.0,bottom=50.0}},
    ExpectBottom = #topological_region{inlet=11,outlet=3, square_flag=false,
        region=#region{left=0.0,top=50.0,right=100.0,bottom=0.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_1_4_test() ->
    TR = #topological_region{inlet=1, outlet=4,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=3,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_2_4_test() ->
    TR = #topological_region{inlet=2, outlet=4,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=3,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_1_5_test() ->
    TR = #topological_region{inlet=1, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_2_5_test() ->
    TR = #topological_region{inlet=2, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_1_6_test() ->
    TR = #topological_region{inlet=1, outlet=6,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_2_6_test() ->
    TR = #topological_region{inlet=2, outlet=6,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_1_9_test() ->
    TR = #topological_region{inlet=1, outlet=9,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=10,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_2_9_test() ->
    TR = #topological_region{inlet=2, outlet=9,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=10,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_1_10_test() ->
    TR = #topological_region{inlet=1, outlet=10,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=10,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_2_10_test() ->
    TR = #topological_region{inlet=2, outlet=10,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=10,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_1_11_test() ->
    TR = #topological_region{inlet=1, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=0,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_2_11_test() ->
    TR = #topological_region{inlet=2, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=0,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
divide_square_1_0_test() ->
    TR = #topological_region{inlet=1, outlet=0,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4,outlet=0,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).    

divide_square_4_0_test() ->
    TR = #topological_region{inlet=4,
        outlet=0, region=#region{left=0.0,top=100.0, right=100.0, bottom=0.0}},
    {Bottom, Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=7, outlet=1, square_flag=false,
        region=#region{left=0.0,top=100.0,right=100.0,bottom=50.0}},
    ExpectBottom = #topological_region{inlet=3,outlet=11, square_flag=false,
        region=#region{left=0.0,top=50.0,right=100.0,bottom=0.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_8_10_test() ->
    TR = #topological_region{inlet=8, outlet=10,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=5,outlet=9,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=9, outlet=1,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).    

divide_square_11_2_test() ->
    TR = #topological_region{inlet=11, outlet=2,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=4,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=8, outlet=2,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

%%%%%%%%%%%%%%%% 0 -> [1,2,3,4,5,6,7,8,9,10,11]
divide_square_0_1_test() ->
    TR = #topological_region{inlet=0, outlet=1,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=4,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=8, outlet=0,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).
    
divide_square_0_2_test() ->
    TR = #topological_region{inlet=0, outlet=2,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=4,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=8, outlet=2,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_0_3_test() ->
    TR = #topological_region{inlet=0, outlet=3,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=0, outlet=4,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=8, outlet=2,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_0_4_test() ->
    TR = #topological_region{inlet=0, outlet=4,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=3,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_5_test() ->
    TR = #topological_region{inlet=0, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_6_test() ->
    TR = #topological_region{inlet=0, outlet=6,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=1,outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_7_test() ->
    TR = #topological_region{inlet=0, outlet=7,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=11,outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=1, outlet=7,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_8_test() ->
    TR = #topological_region{inlet=0, outlet=8,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=11,outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=1, outlet=9,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_9_test() ->
    TR = #topological_region{inlet=0, outlet=8,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=11,outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=1, outlet=9,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_0_10_test() ->
    TR = #topological_region{inlet=0, outlet=10,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4, outlet=10,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_0_11_test() ->
    TR = #topological_region{inlet=0, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right, Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4, outlet=0,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=0, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

%%%%%%%%%%%%%%%% [3,6,9] -> 
%% 6
divide_square_3_7_test() ->
    TR = #topological_region{inlet=3, outlet=7,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=2, outlet=6,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=4, outlet=10,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_3_5_test() ->
    TR = #topological_region{inlet=3, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top,Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=3, outlet=7,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=11, outlet=5,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_3_8_test() ->
    TR = #topological_region{inlet=3, outlet=8,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=4, outlet=10,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_3_11_test() ->
    TR = #topological_region{inlet=3, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=4, outlet=0,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

%% 6
divide_square_6_7_test() ->
    TR = #topological_region{inlet=6, outlet=7,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=2, outlet=6,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=6, outlet=10,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_6_5_test() ->
    TR = #topological_region{inlet=6, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left, Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=6, outlet=2,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=10, outlet=6,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_6_8_test() ->
    TR = #topological_region{inlet=6, outlet=8,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Right,Left} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=2, outlet=8,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=6, outlet=10,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_6_11_test() ->
    TR = #topological_region{inlet=6, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Bottom,Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=5, outlet=11,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=7, outlet=1,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

%% 9
divide_square_9_7_test() ->
    TR = #topological_region{inlet=9, outlet=7,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top, Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=9, outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=1, outlet=7,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_9_5_test() ->
    TR = #topological_region{inlet=9, outlet=5,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Left,Right} = ?MO:divide(TR),
    ExpectLeft = #topological_region{inlet=8, outlet=2,square_flag=false,
        region=#region{left=10.0,top=100.0,right=65.0,bottom=20.0}},
    ExpectRight = #topological_region{inlet=10, outlet=6,square_flag=false,
        region=#region{left=65.0,top=100.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectLeft, Left),
    ?assertEqual(ExpectRight, Right).

divide_square_9_8_test() ->
    TR = #topological_region{inlet=9, outlet=8,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Top, Bottom} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=9, outlet=5,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=1, outlet=9,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

divide_square_9_11_test() ->
    TR = #topological_region{inlet=9, outlet=11,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=20.0}},
    {Bottom, Top} = ?MO:divide(TR),
    ExpectTop = #topological_region{inlet=5, outlet=11,square_flag=false,
        region=#region{left=10.0,top=100.0,right=120.0,bottom=60.0}},
    ExpectBottom = #topological_region{inlet=9, outlet=1,square_flag=false,
        region=#region{left=10.0,top=60.0,right=120.0,bottom=20.0}},
    ?assertEqual(ExpectTop, Top),
    ?assertEqual(ExpectBottom, Bottom).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rotate_test() ->
    Region = #region{left=10.0,top=100.0,right=120.0,bottom=20.0},
    
    ExpectRegion = #region{left=20.0,top=-10.0,right=100.0,bottom=-120.0},
    ?assertEqual(ExpectRegion, rotate_cw_quarter(Region)),
    
    ExpectRegion2 = #region{left=-100.0,top=120.0,right=-20.0,bottom=10.0},
    ?assertEqual(ExpectRegion2, rotate_ccw_quarter(Region)), 
    
    ?assert(Region == rotate_cw_quarter(rotate_ccw_quarter(Region))),
    ?assertEqual(Region, rotate_ccw_quarter(rotate_cw_quarter(Region))).

rotate_region_test() ->
    TR = #topological_region{inlet=1, outlet=3,
                region=#region{left=200.0,top=50.0,right=250.0,bottom=10.0}
            },
    ExpectTR = #topological_region{inlet=4, outlet=6,
                region=#region{left=200.0,top=60.0,right=240.0,bottom=10.0}
            },
    ?assertEqual(TR, rotate_counterclockwise_quarter(rotate_clockwise_quarter(TR))),
    ?assert(TR == rotate_clockwise_quarter(rotate_counterclockwise_quarter(TR))).
